package com.cgnpc.scp.common.utils;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.regex.Pattern;

public class JacksonUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(JacksonUtil.class);

    public static final String STR_SPACE = "^\\s*$";

    public static final Pattern PATTERN_SPACE = Pattern.compile(STR_SPACE);

    /**
     * 是否为空，空白字符串
     *
     * @param str 字符串
     * @return 值true为空或空白字符串；false不为空或空白字符串；
     */
    public static boolean isNullOrSpace(String str) {
        return str == null || str.length() == 0 || PATTERN_SPACE.matcher(str).matches();
    }

    /**
     * 这个应该是多线程安全的吧？？？网上说是多线程安全；简单测试并没有测试出bug；<br>
     */
    private static final ObjectMapper OBJECTMAPPER = new ObjectMapper();

    public static ObjectMapper getObjectMapper() {
        return OBJECTMAPPER;
    }

    /**
     * 将objData对象转换成json字符串
     *
     * @param objectMapper objectMapper
     * @param objData      需要转换成json的对象
     * @return json字符串
     */
    public static String writeValueAsString(ObjectMapper objectMapper, Object objData) {
        if (objectMapper == null || objData == null) {
            return null;
        }

        try {
            return objectMapper.writeValueAsString(objData);
        } catch (IOException e) {
            LOGGER.error("writeValueAsString.objData.error.", e);
            throw new RuntimeException(e);
        }
    }

    public static String writeValueAsString(Object objData) {
        return writeValueAsString(getObjectMapper(), objData);
    }

    public static <T> T readValue(ObjectMapper objectMapper, String content, Class<T> valueType) {
        if (objectMapper == null || isNullOrSpace(content)) {
            return null;
        }

        try {
            // 允许出现特殊字符和转义符
            objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);

            // 允许出现单引号，如{'name':'张三','age':20,\"age000\":123}
            objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);

            // 允许key没有双引号、单引号，如{'name':'张三',age:20}
            objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);

            // 允许字符串中的属性没有映射，如字符串包含name000，对象中不存在name000
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

            return objectMapper.readValue(content, valueType);
        } catch (IOException e) {
            LOGGER.error("readValue.error.", e);
            throw new RuntimeException(e);
        }
    }

    public static <T> T readValue(String content, Class<T> valueType) {
        return readValue(getObjectMapper(), content, valueType);
    }

    public static <T> T readValue(String content, TypeReference<T> valueTypeRef) {
        if (isNullOrSpace(content) || valueTypeRef == null) {
            return null;
        }

        try {
            ObjectMapper objectMapper = getObjectMapper();
            return objectMapper.readValue(content, valueTypeRef);
        } catch (Exception e) {
            LOGGER.error("readValue.error; content:{};", content, e);
            throw new RuntimeException(e);
        }
    }
}
